﻿using PredictionBuilder.Abstract;
using PredictionBuilder.Enum;
using PredictionBuilder.Interfaces;
using PredictionBuilder.Model;
using PredictionBuilder.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace PredictionBuilder.Impl
{
    /// <summary>
    /// 建造者
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TModel"></typeparam>
    public class PredictionBuilder<T, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, TModel> where T : class, new() where TModel : class, new()
    {
        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="model">queryModel</param>
        /// <param name="ignoreValues">忽略值</param>
        public PredictionBuilder(TModel model,params object[] ignoreValues) : base(model, ignoreValues, typeof(T))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) }
            };
        }
        public IPredictionBuilder<T, TModel> SetParameterName(string parameterName)
        {
            NameType = new Dictionary<string, Type>()
            {
                { parameterName,typeof(T)}
            };
            return this;
        }
        public IPredictionBuilder<T, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }
        public Expression<Func<T, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
    public class PredictionBuilder<T, T1, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, TModel>
        where T : class, new()
        where T1 : class, new()
        where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a", typeof(T)},
                {"b", typeof(T1)},
            };
        }

        public IPredictionBuilder<T, T1, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, TModel> SetParameterName(string parameterName, string parameterName1)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName, typeof(T)},
                {parameterName1, typeof(T1)},
            };
            return this;
        }

        public Expression<Func<T, T1, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }

    public class PredictionBuilder<T, T1, T2, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, TModel>
        where T : class, new()
        where T1 : class, new()
        where T2 : class, new()
        where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
            };
        }

        public IPredictionBuilder<T, T1, T2, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
            };
            return this;
        }

        public Expression<Func<T, T1, T2, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
    public class PredictionBuilder<T, T1, T2, T3, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, T3, TModel>
        where T : class, new()
        where T1 : class, new()
        where T2 : class, new()
        where T3 : class, new()
        where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2), typeof(T3))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
                {"d",typeof(T3)},
            };
        }

        public IPredictionBuilder<T, T1, T2, T3, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, T3, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2, string parameterName3)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
                {parameterName3,typeof(T3)}
            };
            return this;
        }

        public Expression<Func<T, T1, T2, T3, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, T3, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
    public class PredictionBuilder<T, T1, T2, T3, T4, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, T3, T4, TModel>
        where T : class, new()
        where T1 : class, new()
        where T2 : class, new()
        where T3 : class, new()
        where T4 : class, new()
        where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
                {"d",typeof(T3)},
                {"e",typeof(T4)},
            };
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2, string parameterName3, string parameterName4)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
                {parameterName3,typeof(T3)},
                {parameterName4,typeof(T4)},
            };
            return this;
        }

        public Expression<Func<T, T1, T2, T3, T4, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, T3, T4, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
    public class PredictionBuilder<T, T1, T2, T3, T4, T5, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, T3, T4, T5, TModel>
        where T : class, new()
        where T1 : class, new()
        where T2 : class, new()
        where T3 : class, new()
        where T4 : class, new()
        where T5 : class, new()
        where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
                {"d",typeof(T3)},
                {"e",typeof(T4)},
                {"f",typeof(T5)},
            };
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2, string parameterName3, string parameterName4, string parameterName5)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
                {parameterName3,typeof(T3)},
                {parameterName4,typeof(T4)},
                {parameterName5,typeof(T5)},
            };
            return this;
        }

        public Expression<Func<T, T1, T2, T3, T4, T5, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, T3, T4, T5, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
    public class PredictionBuilder<T, T1, T2, T3, T4, T5, T6, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, TModel>
        where T : class, new()
        where T1 : class, new()
        where T2 : class, new()
        where T3 : class, new()
        where T4 : class, new()
        where T5 : class, new()
        where T6 : class, new()
        where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
                {"d",typeof(T3)},
                {"e",typeof(T4)},
                {"f",typeof(T5)},
                {"g",typeof(T6)},
            };
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2, string parameterName3, string parameterName4, string parameterName5, string parameterName6)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
                {parameterName3,typeof(T3)},
                {parameterName4,typeof(T4)},
                {parameterName5,typeof(T5)},
                {parameterName6,typeof(T6)},
            };
            return this;
        }

        public Expression<Func<T, T1, T2, T3, T4, T5, T6, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, T3, T4, T5, T6, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }

    }
    public class PredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, TModel>
       where T : class, new()
       where T1 : class, new()
       where T2 : class, new()
       where T3 : class, new()
       where T4 : class, new()
       where T5 : class, new()
       where T6 : class, new()
       where T7 : class, new()
       where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
                {"d",typeof(T3)},
                {"e",typeof(T4)},
                {"f",typeof(T5)},
                {"g",typeof(T6)},
                {"h",typeof(T7)},
            };
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2, string parameterName3, string parameterName4, string parameterName5, string parameterName6, string parameterName7)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
                {parameterName3,typeof(T3)},
                {parameterName4,typeof(T4)},
                {parameterName5,typeof(T5)},
                {parameterName6,typeof(T6)},
                {parameterName7,typeof(T7)},
            };
            return this;
        }

        public Expression<Func<T, T1, T2, T3, T4, T5, T6, T7, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, T3, T4, T5, T6, T7, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
    public class PredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, TModel>
        where T : class, new()
       where T1 : class, new()
       where T2 : class, new()
       where T3 : class, new()
       where T4 : class, new()
       where T5 : class, new()
       where T6 : class, new()
       where T7 : class, new()
       where T8 : class, new()
       where TModel : class, new()
    {
        public PredictionBuilder(TModel model, params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
                {"d",typeof(T3)},
                {"e",typeof(T4)},
                {"f",typeof(T5)},
                {"g",typeof(T6)},
                {"h",typeof(T7)},
                {"i",typeof(T8)},
            };
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2, string parameterName3, string parameterName4, string parameterName5, string parameterName6, string parameterName7, string parameterName8)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
                {parameterName3,typeof(T3)},
                {parameterName4,typeof(T4)},
                {parameterName5,typeof(T5)},
                {parameterName6,typeof(T6)},
                {parameterName7,typeof(T7)},
                {parameterName8,typeof(T8)},
            };
            return this;
        }

        public Expression<Func<T, T1, T2, T3, T4, T5, T6, T7, T8, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, T3, T4, T5, T6, T7, T8, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
    public class PredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, TModel> : AbstractBuilder<TModel>, IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, TModel>
       where T : class, new()
       where T1 : class, new()
       where T2 : class, new()
       where T3 : class, new()
       where T4 : class, new()
       where T5 : class, new()
       where T6 : class, new()
       where T7 : class, new()
       where T8 : class, new()
       where T9 : class, new()
       where TModel : class, new()
    {
        public PredictionBuilder(TModel model,params object[] ignoreValues) : base(model, ignoreValues, typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9))
        {
            NameType = new Dictionary<string, Type>()
            {
                {"a",typeof(T) },
                {"b",typeof(T1)},
                {"c",typeof(T2)},
                {"d",typeof(T3)},
                {"e",typeof(T4)},
                {"f",typeof(T5)},
                {"g",typeof(T6)},
                {"h",typeof(T7)},
                {"i",typeof(T8)},
                {"k",typeof(T9)},
            };
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, TModel> SetAggregateCondition(ConnectType outerJoinType = ConnectType.And, params Expression<Func<TModel, object>>[] selectors)
        {
            AddAggregateCondition(outerJoinType, selectors);
            return this;
        }

        public IPredictionBuilder<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, TModel> SetParameterName(string parameterName, string parameterName1, string parameterName2, string parameterName3, string parameterName4, string parameterName5, string parameterName6, string parameterName7, string parameterName8, string parameterName9)
        {
            NameType = new Dictionary<string, Type>()
            {
                {parameterName,typeof(T) },
                {parameterName1,typeof(T1)},
                {parameterName2,typeof(T2)},
                {parameterName3,typeof(T3)},
                {parameterName4,typeof(T4)},
                {parameterName5,typeof(T5)},
                {parameterName6,typeof(T6)},
                {parameterName7,typeof(T7)},
                {parameterName8,typeof(T8)},
                {parameterName9,typeof(T9)},
            };
            return this;
        }

        public Expression<Func<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>> ToExpression()
        {
            InitParmeterMap();
            var orginExp = CreatePredition<Func<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, bool>>(builderModel.PropertyBuildInfos.Where(t => !t.IsAggregate && t.TargetType.Any()),
                (orgin, exp, propInfo) => ExpressionHelper.JoinExpression(orgin, exp, propInfo.ConnectAttribute.ConnectType));
            return CreateAggregatePredition(orginExp, aggregateInfos);
        }
    }
}
